/**
 * Created by LeungZ on 2016/10/15.
 */
import rules from './rules.js';
import parser from './parser.js';
import helper from './helper.js';

helper.initLineRulesRegexes(rules);
var commandValidators = {
    'LABEL': helper.validateNameVals,
    'ARG': helper.validateNameVals,
    'ENV': helper.validateNameVals
};

var context = {
    rules: rules,
    validInstructionsRegex: helper.createValidCommandRegex(rules.general.valid_instructions),
    requiredInstructions: helper.createReqInstructionHash(rules),
    requiredNameVals: helper.createRequiredNameValDict(rules)
};

function finish(result) {
    return result;
}

function validateCommand(command, context, result) {
    if (command.error) {
        helper.addError(result, command.lineno, command.raw, command.error, null);
    }
    var rules = context.rules;

    var isValid = context.validInstructionsRegex.test(command.raw);
    if (!isValid) {
        helper.addError(result, command.lineno, command.raw, 'Invalid instruction', null);
        return false;
    }
    var instruction = command.name.trim().toUpperCase();
    // Update existence hash for later check
    if (instruction in context.requiredInstructions) {
        context.requiredInstructions[instruction].exists = true;
    }
    helper.checkLineRules(rules, instruction, command.raw, command.lineno, result);
    if (rules.line_rules[instruction] && rules.line_rules[instruction].paramSyntaxRegex) {
        var stringParams = command.raw.replace(instruction, '').trim();
        var validParams = rules.line_rules[instruction].paramSyntaxRegex.test(stringParams);
        if (!validParams) {
            helper.addError(result, command.lineno, command.raw, 'Invalid parameters for command.', null);
            return false;
        }
    }
    var commandValidatorFn = commandValidators[command.name];
    if (commandValidatorFn) {
        commandValidatorFn(command, context, result);
    }
}

export default {
    validate: function (contents) {
        var result = helper.newResult();
        var options = {includeComments: false};
        // @see  parser.parse for format of commands
        var commands = parser.parse(contents, options);

        if (commands.length < 1) {
            /* skip throw error for null
             helper.addError(result, 0, null,"Invalid Dockerfile. No commands found!", null);
             */
            return finish(result);
        }
        if (commands[0].name !== 'FROM') {
            helper.addError(result, commands[0].lineno, commands[0].raw,
                'Missing or misplaced FROM', null);
        }
        for (var i = 0; i < commands.length; i++) {
            validateCommand(commands[i], context, result);
        }
        helper.checkRequiredInstructions(context.requiredInstructions, result);
        helper.checkRequiredNameVals(context.requiredNameVals, result);
        return finish(result);
    }
};